﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Reflection;
using System.Xml;
using FinPlusCommon;
using FinPlusWCFConnData;
using log = Logger.Logger;
using u = FinPlusUtility.Utility;

namespace FinPlusWPFControls
{
    public abstract class FinPlusControl : UserControl, IFinPlusComponent
    {
        public abstract string Id { get; set; }
        public abstract IFinPlusFunctions Model { get; }
        public abstract string[] States { get; }
        public abstract string[] TestStates { get; }
        public abstract bool IsValid { get; set; }
        public abstract string ModelTest { get; }

        public string User { get { return _user == null ? _user = Environment.UserName : _user; } }
        public u.Env Env { get { return _env; } set { _env = _env == u.Env.unknown ? value : _env; }}
        public IFinPlusFunctions Commands { get { return _commands; } set { _commands = value; } }
        public IFinPlusFunctions Structure { get { return _structure = _structure == null ? GetStructure() : _structure; } }
        public string Config { get { return _config; } set { _config = string.IsNullOrEmpty(_config) ? value : _config; } }

        private enum Params { Group, Id, Environment, Config, ClientConfig, From, Security, User, Structure, Trigger, FunctionMap, Audit, FunctionName, FuncHasBeenSaved }

        private volatile static FinPlusParentService _audit;
        private volatile static Permissions _permissions;
        private volatile static Groups _groups;
        private volatile static IFinPlusFunctions _structure;
        private static IFinPlusFunctions _commands;
        private static Object _lock = new Object();
        private static u.Env _env = u.Env.unknown;
        private static string _config, _user;
        private Permission _environmentPerm, _configPerm, _groupPerm;

        //construct
        protected FinPlusControl() { }

        //common control interface
        public abstract void Dock(object control, string dock);

        public abstract void Initialise();

        public abstract void CommandRouter(IFinPlusFunction func);
        
        public abstract void Dispose();

        //public
        public Dock ParseDock(string value, Dock defaultValue = System.Windows.Controls.Dock.Top)
        {
            Dock res;
            if (Enum.TryParse(value, out res)) return res;
            return defaultValue;
        }

        public UserControl DockSet(UserControl control, string dock)
        {
            DockPanel.SetDock((UserControl)control, ParseDock(dock));
            return control;
        }

        public IFinPlusFunctions Children(UIElementCollection elements)
        {
            var funcs = new Functions();
            foreach (var child in elements)
                funcs.Add(new Function() { Object = child });

            return funcs;
        }

        public void CaptureCommand(IFinPlusFunction func)
        {
            if (_commands == null || func[Params.FuncHasBeenSaved.ToString()].ToString().Equals(true.ToString()))
                return;

            _commands.Add(func);
            func[Params.FuncHasBeenSaved.ToString()] = true;
        }

        public Permission GetPermission(string name, string itemName, string itemValue = null)
        {
            try
            {
                if (itemValue == null) itemValue = itemName;

                GetPermissions();
                
                GetGroups();
                    
                //layer 4 function 
                var funcPerm = itemValue.Equals("-1") ? new Permission(true, true) : _permissions.Get(User, name, itemName, itemValue);

                //layer 3 group 
                if (name.Equals(Params.Group.ToString()) || name.Equals(Params.Environment.ToString()) || name.Equals(Params.ClientConfig.ToString()))
                    _groupPerm = funcPerm;
                else if (_groups.ContainsKey(name))
                    _groupPerm = _permissions.Get(User, Params.Group.ToString(), _groups[name], _groups[name]);
                else
                    _groupPerm = new Permission(false, false);

                //layer 2 app
                if (_configPerm == null) _configPerm = _permissions.Get(User, Params.ClientConfig.ToString(), _config, _config);

                //layer 1 environment 
                if (_environmentPerm == null) _environmentPerm = _permissions.Get(User, Params.Environment.ToString(), Env.ToString(), Env.ToString());
              
                return  _environmentPerm + _configPerm + _groupPerm + funcPerm;
            }
            catch
            {
                return new Permission(false, false);
            }
        }

        public Permission GetPermission(IFinPlusFuncDynamic func)
        {
            object funcName, funcId;

            if (func.TryGetObject(Params.FunctionName.ToString(), out funcName) && func.TryGetObject(Params.Id.ToString(), out funcId))
                return GetPermission(funcName.ToString(), Params.Id.ToString(), funcId.ToString());

            return new Permission(false, false);
        }

        public async void SaveAudit(string trigger, IFinPlusFunction[] funcs)
        {
            GetAudit();

            await Task.Run(() =>
            {
                var audit = new Function(Params.Audit.ToString(), null, User, -1);
                audit[Params.Environment.ToString(), User] = _env.ToString();
                audit[Params.Config.ToString(), User] = _config.ToString();
                audit[Params.From.ToString(), User] = "Client";
                audit[Params.User.ToString(), User] = User;
                audit[Params.Trigger.ToString(), User] = trigger;

                int x = 1;
                foreach (var func in funcs)
                    audit.Add(string.Format("Link{0}", x++),-1, func.Id, func, User, DateTime.MinValue);

                _audit.Save(audit);
            });
        }

        //private
        private void GetPermissions()
        {
            if (_permissions == null)
            {
                lock (_lock)
                {
                    if (_permissions == null)
                    {
                        var conn = new FinPlusParentService(Params.Security.ToString(), "[group],Security;[type],Select;[where],Name='User' And Value='" + User + "'", string.Empty, false);
                        _permissions = new Permissions(conn.Model);
                    }
                }
            }
        }

        private IFinPlusFunctions GetStructure()
        {
            if (_structure == null)
            {
                lock (_lock)
                {
                    if (_structure == null)
                    {
                        var conn = new FinPlusParentService(Params.Structure.ToString(), "[group],Structure;[type],Select;[where],", string.Empty, false);
                        _structure = conn.Model;
                    }
                }
            }
            return _structure;
        }

        private void GetGroups()
        {
            if (_groups == null)
            {
                lock (_lock)
                {
                    if (_groups == null)
                    {
                        var conn = new FinPlusParentService(Params.FunctionMap.ToString(), "[group],FunctionMap;[type],Select;[where],", string.Empty, false);
                        _groups = new Groups(conn.Model);
                    }
                }
            }
        }

        private void GetAudit()
        {
            if (_audit == null)
            {
                lock (_lock)
                {
                    if (_audit == null)
                        _audit = new FinPlusParentService(Params.Audit.ToString(), "[group],Audit;[type],SaveFunc;[where],", string.Empty, false);
                }
            }
        }
    }
}


































































































































//Copyright2013<jnrton>AllRightsReserved 
//Contact j.nrton@finpus